package com.xuecheng.content.service.jobhandler;

import com.xuecheng.base.exception.XueChengPlusException;
import com.xuecheng.content.feignclient.CourseIndex;
import com.xuecheng.content.feignclient.SearchServiceClient;
import com.xuecheng.content.mapper.CoursePublishMapper;
import com.xuecheng.content.model.dto.CoursePreviewDto;
import com.xuecheng.content.model.po.CoursePublish;
import com.xuecheng.content.service.CoursePublishService;
import com.xuecheng.messagesdk.model.po.MqMessage;
import com.xuecheng.messagesdk.service.MessageProcessAbstract;
import com.xuecheng.messagesdk.service.MqMessageService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.File;

/**
 * 课程发布任务类
 */
@Slf4j
@Component
public class CoursePublishTask extends MessageProcessAbstract {

    @Autowired
    private CoursePublishService coursePublishService;

    @Autowired
    private SearchServiceClient searchServiceClient;

    @Autowired
    private CoursePublishMapper coursePublishMapper;

    //任务调度入口
    @XxlJob("CoursePublishJobHandler")
    public void coursePublishJobHandler() throws Exception{
        // 分片参数
        int shardIndex = XxlJobHelper.getShardIndex(); //执行器的序号
        int shardTotal = XxlJobHelper.getShardTotal(); //执行器的总数

        //调用已有的抽象类
        process(shardIndex, shardTotal, "course_publish", 30, 60);
    }

    /**
     * 执行课程发布任务的逻辑
     * @param mqMessage 执行任务内容
     * @return
     */
    @Override
    public boolean execute(MqMessage mqMessage) {
        //从mqMessage中获取课程id
        Long courseId = Long.valueOf(mqMessage.getBusinessKey1());

        //向课程静态化上传到minio
        generateCourseHtml(mqMessage, courseId);

        //向elasticsearch写入索引数据
        saveCourseIndex(mqMessage, courseId);

        //向redis写缓存


        return true;
    }

    /**
     * 生成课程静态化页面并上传到文件系统 ,StageOne
     * @param mqMessage
     * @param courseId
     */
    private void generateCourseHtml(MqMessage mqMessage, long courseId){
        //任务幂等性,考虑多线程，所以去status时要从数据库中读取
        Long taskId = mqMessage.getId();
        MqMessageService mqMessageService = this.getMqMessageService();
        //获取stage
        int stageOne = mqMessageService.getStageOne(taskId);

        if(stageOne > 0){
            log.debug("课程静态化完成，无需处理...");
            return;
        }

        //开始进行静态化,生成html页面
        File file = coursePublishService.generateCourseHtml(courseId);
        if(file == null){
            XueChengPlusException.cast("生成的静态页面为空");
        }

        //将生成的html页面上传到minio
        coursePublishService.uploadCourseHtml(courseId, file);

        //任务处理完成，修改状态stage为1
        mqMessageService.completedStageOne(taskId);
    }

    /**
     * 保存课程索引信息,StageTwo
     * @param mqMessage
     * @param courseId
     */
    public void saveCourseIndex(MqMessage mqMessage, long courseId){
        //任务幂等性,考虑多线程，所以去status时要从数据库中读取
        Long taskId = mqMessage.getId();
        MqMessageService mqMessageService = this.getMqMessageService();
        //获取stage
        int stageTwo = mqMessageService.getStageTwo(taskId);

        if(stageTwo > 0){
            log.debug("课程索引已写入，无需处理...");
            return;
        }

        //查询课程信息
        CoursePublish coursePublish = coursePublishMapper.selectById(courseId);

        //调用搜索服务添加索引
        CourseIndex courseIndex = new CourseIndex();
        BeanUtils.copyProperties(coursePublish, courseIndex);

        //远程调用
        Boolean add = searchServiceClient.add(courseIndex);
        if(!add){
            XueChengPlusException.cast("添加索引失败！");
        }

        //完成任务
        mqMessageService.completedStageTwo(taskId);
    }

    /**
     * 将课程信息缓存至redis
     * @param mqMessage
     * @param courseId
     */
    public void saveCourseCache(MqMessage mqMessage, long courseId){
        //任务幂等性,考虑多线程，所以去status时要从数据库中读取
        Long taskId = mqMessage.getId();
        MqMessageService mqMessageService = this.getMqMessageService();
        //获取stage
        int stageThree = mqMessageService.getStageThree(taskId);

        if(stageThree > 0){
            log.debug("课程索引已写入，无需处理...");
            return;
        }

        //将课程信息缓存至redis

        //完成任务
        mqMessageService.completedStageThree(taskId);
    }

}
